/**
 * 
 */
package it.polimi.cg16.net;

import it.polimi.cg16.controller.Game;
import it.polimi.cg16.controller.PlayerController;
import it.polimi.cg16.exceptions.InactivePlayerException;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Andrea & Michele
 * 
 */
public class SocketAdapter implements Adapter {
    private static final Logger LOGGER = Logger.getGlobal();
    private static final String CONTEXT = "context";

    ObjectOutputStream out;
    ObjectInputStream in;
    String message;
    private PlayerController playerController;

    public SocketAdapter(Socket connection) {
        System.out.println("Connection received from " + connection.getInetAddress().getHostName());
        // 3. get Input and Output streams

        try {
            out = new ObjectOutputStream(connection.getOutputStream());
            out.flush();
            in = new ObjectInputStream(connection.getInputStream());
            sendMessage("Connection successful");
            // 4. The two parts communicate via the input and output streams
            // byeMessage();
        } catch (IOException ioException) {
            LOGGER.log(Level.FINE, CONTEXT, ioException);
        }
    }

    /**
     * Close the connection
     */
    private void closeConnection() {
        // 4: Closing connection
        try {
            in.close();
            out.close();
        } catch (IOException ioException) {
            LOGGER.log(Level.FINE, CONTEXT, ioException);
        }
    }

    /**
     * Send a bye message
     * 
     * @throws IOException
     */
    public void byeMessage() {
        sendMessage("bye");
        closeConnection();
    }

    /**
     * Set the player controller to the adapter
     * 
     * @param playerController
     */
    public void setPlayerController(PlayerController playerController) {
        this.playerController = playerController;
    }

    /**
     * Method to show result to client
     */
    @Override
    public void showResults(Game game) {
        sendMessage("#showResults#");
        sendInt(playerController.getPlayer().getPoints());
    }

    /**
     * Receive string from client
     * 
     * @return
     * @throws IOException
     */
    @Override
    public String readString() throws InactivePlayerException {
        String s = null;
        try {
            s = (String) in.readObject();
        } catch (ClassNotFoundException e) {
            LOGGER.log(Level.FINE, CONTEXT, e);
        } catch (IOException e) {
            LOGGER.log(Level.FINE, CONTEXT, e);
            throw new InactivePlayerException();
        }
        return s;
    }

    /**
     * Receive integer from client
     * 
     * @return
     * @throws IOException
     */
    @Override
    public int readInt() throws InactivePlayerException {
        int i = 0;
        try {
            i = in.readInt();
        } catch (IOException e) {
            LOGGER.log(Level.FINE, CONTEXT, e);
            throw new InactivePlayerException();
        }
        return i;
    }

    /**
     * Send integer to the client
     * 
     * @param num
     */
    @Override
    public void sendInt(int num) {
        try {
            out.reset();
            out.writeInt(num);
            out.flush();
        } catch (IOException ioException) {
            LOGGER.log(Level.FINE, CONTEXT, ioException);
        }

    }

    /**
     * Send message to the client
     */
    @Override
    public void sendMessage(String msg) {
        try {
            out.reset();
            out.writeObject(msg);
            out.flush();
        } catch (IOException ioException) {
            LOGGER.log(Level.FINE, CONTEXT, ioException);
        }
    }

}
